/**
 * Copyright (C) 2013 DaiKit.com - daikit4gxt module (admin@daikit.com)
 *
 *         Project home : http://code.daikit.com/daikit4gxt
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.daikit.daikit4gxt.client.action;

import java.io.Serializable;

import com.sencha.gxt.data.shared.ListStore;
import com.sencha.gxt.data.shared.loader.ListLoadConfig;
import com.sencha.gxt.data.shared.loader.ListLoadResult;
import com.sencha.gxt.data.shared.loader.ListLoader;
import com.sencha.gxt.data.shared.loader.LoadResultListStoreBinding;


/**
 * Base Loader for {@link ListStore} without paging
 * 
 * @author tcaselli
 * @version $Revision$ Last modifier: $Author$ Last commit: $Date$
 * @param <B>
 *           the type of the beans returned in the {@link ListLoadResult}
 * @param <C>
 *           the type of the given {@link ListLoadConfig}
 * @param <D>
 *           the type of the RPC returned {@link ListLoadResult}
 */
public abstract class DkBaseListLoader<B extends Serializable, C extends ListLoadConfig, D extends ListLoadResult<B>> extends
		ListLoader<C, D>
{
	private String loadingProgressMessage;
	private boolean showProgress;

	/**
	 * Constructor with showProgress = false;
	 * 
	 * @param store
	 *           the {@link ListStore} to be re-populated when received new {@link ListLoadResult}
	 * @param loadingProgressMessage
	 *           the loading progress message
	 */
	public DkBaseListLoader(final ListStore<B> store, final String loadingProgressMessage)
	{
		this(store, loadingProgressMessage, true);
	}

	/**
	 * Constructor
	 * 
	 * @param store
	 *           the {@link ListStore} to be re-populated when received new {@link ListLoadResult}
	 * @param loadingProgressMessage
	 *           the loading progress message
	 * @param showProgress
	 *           boolean indicating whether progress bar should be shown (or incremented if already shown) for this
	 *           action
	 */
	public DkBaseListLoader(final ListStore<B> store, final String loadingProgressMessage, final boolean showProgress)
	{
		super(new DkBaseListLoaderRpcProxy<B, C, D>());
		this.loadingProgressMessage = loadingProgressMessage;
		this.showProgress = showProgress;
		addLoadHandler(new LoadResultListStoreBinding<C, B, D>(store));
	}

	@SuppressWarnings("unchecked")
	@Override
	public DkBaseListLoaderRpcProxy<B, C, D> getProxy()
	{
		return (DkBaseListLoaderRpcProxy<B, C, D>) super.getProxy();
	}

	void loadFromAction(final DkLoadAction<B, C, D> loadAction)
	{
		getProxy().setBaseLoadAction(loadAction);
		super.load();
	}

	@Override
	public boolean load()
	{
		getProxy().setBaseLoadAction(getReloadAction());
		return super.load();
	}

	void doLoad(final C listLoadConfig)
	{
		doLoad(listLoadConfig, new DkBaseAsyncCallback<D>(getProxy().getBaseLoadAction(), true)
		{
			@Override
			public void processSuccess(final D result)
			{
				DkBaseListLoader.this.processLoadSuccess(result);
			}

			@Override
			public boolean processFailure(final Throwable caught)
			{
				return DkBaseListLoader.this.processLoadFailure(caught);
			}
		});
	}

	protected abstract void doLoad(final C listLoadConfig, final DkBaseAsyncCallback<D> callback);

	/**
	 * Called by the Callback from BaseAsyncCallback.
	 * 
	 * @see {@link DkBaseAsyncCallback#processSuccess(Object)}
	 * @param result
	 */
	protected void processLoadSuccess(final D result)
	{
		getProxy().getBaseLoadAction().getProxyAsyncCallback().onSuccess(result);
	}

	/**
	 * Called by the Callback from BaseAsyncCallback.
	 * 
	 * @see {@link DkBaseAsyncCallback#processFailure(Throwable)}
	 * @param caught
	 * @return
	 */
	protected boolean processLoadFailure(final Throwable caught)
	{
		getProxy().getBaseLoadAction().getProxyAsyncCallback().onFailure(caught);
		return true;
	}

	/**
	 * Return a new reload action.
	 * 
	 * @return a new reload action instance.
	 */
	public DkLoadAction<B, C, D> getReloadAction()
	{
		return new DkLoadAction<B, C, D>(loadingProgressMessage, showProgress, this);
	}
}
